home *** CD-ROM | disk | FTP | other *** search
/ Hottest 6 / Hottest 6 (1996)(PDSoft)[!].iso / software / programming / c / objective / docs / plain.doc
Text File  |  1978-11-24  |  68KB  |  1,657 lines

  1. *Premessa*
  2.  
  3. Nello sviluppo di una applicazione che richiede una complessa interfaccia utente
  4. si fa un largo uso di oggetti chiamati gadget.  Questi oggetti sono di tipo
  5. diverso e servono a scopi differenti.  Per questo Intuition permette, dalla
  6. versione 2.0 del Sistema Operativo, la possibilità di creare dei gadget
  7. personalizzati detti "custom gadget".  Il metodo che usa Intuition per operare
  8. su questi gadget è quello di chiamare una funzione utente.  In questo modo è
  9. possibile implementare qualsiasi tipo di gadget.
  10.  
  11. Oltre a questa novità è stata distribuita, sempre con il 2.0, la
  12. gadtools.library:  una libreria dei gadget più usati dagli applicativi utente e
  13. di sistema.  Questa libreria è però ritenuta insufficiente per molte
  14. applicazioni e quindi ne viene proposta un'altra in queste pagine.
  15.  
  16.  
  17. *Descrizione Della Libreria*
  18.  
  19. La libreria si chiama ObjectiveGadTools (da ora in avanti OGT) ed è stata
  20. scritta sfruttando il meccanismo dei BOOPSI di Intuition; ogni gadget (oggetto)
  21. appartiene ad una classe e ha dei dati propri.  L'applicativo non può modificare
  22. nè leggere i dati locali all'oggetto se non tramite i metodi generali dei BOOPSI
  23. ed in particolare i metodi OM_SET ed OM_GET.  A differenza dalla GadTools, nella
  24. quale l'uso dei tag era limitato solo alla comunicazione dall'applicativo al
  25. sistema, nella OGT tutto si attua per mezzo di liste di TagItem, in quanto non
  26. fa alcuna differenza per un oggetto il comunicare con un altro oggetto o con
  27. l'applicativo.
  28.  
  29. Le novità principali della OGT rispetto alla GadTools sono:
  30.  
  31.  + posizionamento relativo degli oggetti rispetto ad altri oggetti e rispetto alla
  32.    finestra.
  33.  + ridimensionamento degli oggetti a tempo d'esecuzione.
  34.  + adattamento automatico al font usato o alle dimensioni della finestra.
  35.  + gestione dell'Help contestuale all'oggetto.
  36.  + gestione trasparente delle abbreviazioni da tastiera (short-cut).
  37.  + sensibilità al rilascio delle icone sugli oggetti.
  38.  + creazione di oggetti più potenti quali gadget con immagini vettoriali o
  39.    gadget file-request.
  40.  
  41. La mancanza di queste basilari particolarità fa della GadTools uno strumento
  42. limitato che male si presta alla programmazione orientata agli oggetti.  Questo
  43. è dovuto ad una impostazione differente di progetto, sarà molto difficile fare
  44. in modo che la GadTools evolva nel senso che noi speriamo restando compatibile
  45. con le applicazioni attuali.
  46.  
  47. Inoltre si è cercato di rendere il più semplice possibile anche l'allocazione e
  48. la gestione degli oggetti messi a disposizione dalla libreria, con un occhio di
  49. riguardo ai programmi costruttori di applicativi:  è possibile definire tutta
  50. un'applicazione (per quanto riguarda l'aspetto grafico) con solo strutture
  51. statiche, in modo che il codice da aggiungere sia minimo, giusto:
  52.  
  53. --------------------------------------------------------------------------------
  54.  APTR            VInfo;
  55.  struct Window  *Win;
  56.  struct Gadget **Gads;
  57.  
  58.  VInfo = OGT_GetVisualInfoA( NULL,
  59.                              WindowDescTags );
  60.  
  61.  OGT_BuildObjects( VInfo,
  62.                    ArrayOfObjects,
  63.                    ArrayOfLinks,
  64.                    &Gads );
  65.  
  66.  Win = OGT_GetWindowPtr( VInfo );
  67.  
  68.  ...
  69.  
  70.  Gestione applicazione
  71.  
  72.  ...
  73.  
  74.  OGT_FreeVisualInfo( VInfo );
  75. --------------------------------------------------------------------------------
  76.  
  77. Il significato delle funzioni è precisato più avanti.
  78.  
  79.  
  80. *Descrizione degli oggetti*
  81.  
  82. Gli oggetti definiti dalla OGT sono al momento questi:
  83.  
  84.  + GROUP_OGT_CLASS
  85.  + BUTTON_OGT_CLASS
  86.  + STRING_OGT_CLASS
  87.  + PROP_OGT_CLASS
  88.  + SCROLLER_OGT_CLASS
  89.  + MULTIWAY_OGT_CLASS
  90.  + LISTVIEW_OGT_CLASS
  91.  + ASLREQ_OGT_CLASS
  92.  + SHOWTEXT_OGT_CLASS
  93.  + SHOWLIST_OGT_CLASS
  94.  + MENU_OGT_CLASS
  95.  
  96. In realtà alcuni oggetti hanno un comportamento multiplo, per esempio gli
  97. oggetti della classe BUTTON_OGT_CLASS inglobano le funzionalità dei gadget
  98. BUTTON_KIND e CYCLE_KIND della GadTools, quelli della classe MULTIWAY_OGT_CLASS
  99. le funzionalità dei gadget MX_KIND e CHECKBOX_KIND e quelli della classe
  100. SHOWTEXT_OGT_CLASS le funzionalità delle controparti NUMBER_KIND e TEXT_KIND,
  101. solitamente anche con miglioramenti.
  102.  
  103. Tutti le classi rispondono in maniera uguale ad un insieme ben definito di tag
  104. (in quanto sono tutte derivate da due classi private, che si occupano
  105. dell'immagine, delle caratteristiche geometriche e della comunicazione fra gli
  106. oggetti).
  107.  
  108.  
  109. **Tag comuni**
  110.  
  111. - GA_Disabled        USHORT
  112.  
  113. Abilita o meno l'input da utente.  Se TRUE l'oggetto si porrà in uno stato di
  114. inibizione dell'input, mostrando un aspetto "ghosted", accettando però eventuali
  115. comunicazioni da parte di altri oggetti o dell'applicazione.
  116.  
  117.  
  118. - GA_ID              USHORT
  119.  
  120. Il numero con cui viene identificato un oggetto:  quando un oggetto deve
  121. notificare un qualche evento, lo fa con questo valore, per mezzo del tag OGT_ID.
  122.  
  123.  
  124. - OGT_Object         Object *
  125.  
  126. E' il puntatore ad un oggetto.  Viene inserito in tutti i messaggi generati
  127. dagli oggetti, per rendere molto semplice l'identificazione del mittente del
  128. messaggio.
  129.  
  130.  
  131. - ICA_TARGET         Object *
  132.  
  133. E' il puntatore all'oggetto a cui bisogna mandare i messaggi di tipo OM_UPDATE.
  134. Contrariamente agli oggetti messi a disposizione da Intuition, gli oggetti della
  135. OGT di default comunicano con l'applicazione.  Nel caso ciò non fosse
  136. desiderabile, basta passare un NULL con questo tag.
  137.  
  138.  
  139. - ICA_MAP            struct TagItem *
  140.  
  141. Si tratta di una lista di TagItem, che serve per tradurre i tag dal dominio
  142. dell'oggetto mittente al dominio dell'oggetto destinatario.  Ad esempio, se si
  143. devono connettere A e B, con A che emette PGA_Top e B che capisce
  144. STRINGA_LongVal, bisogna inserire un'applicazione che trasformi PGA_Top in
  145. STRINGA_LongVal, cioè:
  146.  
  147. --------------------------------------------------------------------------------
  148.  struct TagItem MapAtoB[] =
  149.  {
  150.     { PGA_Top , STRINGA_LongVal },
  151.     { TAG_DONE                  }
  152.  };
  153. --------------------------------------------------------------------------------
  154.  
  155. - OGT_VisualInfo     APTR
  156.  
  157. E' assolutamente necessario, senza di esso l'oggetto non si alloca neanche.  Il
  158. dato da passare è il puntatore ritornato da OGT_GetVisualInfoA().
  159.  
  160.  
  161. - OGT_LinkToAnchor   BOOL  default: TRUE
  162.  
  163. Serve per specificare se la classe deve tener traccia dell'allocazione
  164. dell'oggetto, in modo che questo venga liberato da una successiva chiamata a
  165. OGT_FreeVisualInfo().  Praticamente attacca o meno l'oggetto alla GadgetList
  166. della finestra e quindi non c'è più bisogno di tag come GA_Previous o GA_Next.
  167. Se non viene specificato altrimenti l'allocazione viene ricordata (oggetto
  168. aggiunto alla lista).  Ma se un oggetto deve essere agganciato ad un gruppo,
  169. dato che la responsabilità della liberazione delle risorse degli oggetti
  170. attaccati ad un gruppo è del gruppo stesso, bisognerà specificare FALSE, per
  171. evitare una liberazione di risorse già liberate, cosa che porta ad un sicuro
  172. blocco del sistema.
  173.  
  174.  
  175. - OGT_Parent         Object *
  176.  
  177. Indica che l'oggetto deve essere agganciato ad un certo gruppo.  Ciò determina
  178. anche una modificazione nel modo in cui l'oggetto è disegnato, cioè sarà
  179. disegnato relativamente all'oggetto a cui è agganciato, non alla finestra.  Dato
  180. che per un oggetto essere riferito alla finestra o ad un altro oggetto è la
  181. stessa cosa, in futuro si farà riferimento al generico dominio in cui giace un
  182. oggetto.  Per esempio, con alcuni settaggi un oggetto può essere riferito al
  183. bordo destro di una finestra (con GA_RightBorder = TRUE) e quindi in questo caso
  184. dire che si vuole un oggetto grande come il dominio è equivalente a dire che si
  185. vuole un oggetto grande come il bordo destro della finestra.  Naturalmente ci
  186. sono casi in cui è desiderabile che l'oggetto faccia distinzione fra essere
  187. all'interno di una finestra o "nella" finestra, per ragioni estetiche o
  188. funzionali, ma sarà sempre cura della classe dell'oggetto operare una
  189. differenziazione, come ad esempio la SCROLLER_OGT_CLASS.
  190.  
  191.  
  192. - GA_Left
  193. - GA_Top
  194. - GA_Width
  195. - GA_Height          WORD
  196.  
  197. Indicano la posizione e le dimensioni dell'oggetto.  Il loro significato reale
  198. varia in funzione di ulteriori precisazioni delle caratteristiche geometriche
  199. degli oggetti.
  200.  
  201.  
  202. - GA_RelRight
  203. - GA_RelBottom       WORD
  204.  
  205. Servono per riferire la posizione dell'oggetto rispetto ai bordi destro e
  206. inferiore, contrariamente a quanto accade di solito, con la posizione riferita
  207. ai bordi sinistro e superiore.
  208.  
  209.  
  210. - GA_RelWidth
  211. - GA_RelHeight       WORD
  212.  
  213. Anzichè assolute, le dimensioni di un oggetto vengono specificate come relative
  214. rispetto alle dimensioni del dominio in cui giace.
  215.  
  216.  
  217. - OGT_Right
  218. - OGT_Bottom         WORD
  219.  
  220. Questi due tag introducono uno dei tanti nuovi modi per definire un oggetto.
  221. Normalmente si definisce un oggetto per mezzo della coordinata di un suo punto e
  222. le sue dimensioni.  Con questi tag si può definire un oggetto mediante due
  223. coordinate, quella dell'angolo superiore sinistro e quella dell'angolo inferiore
  224. destro.
  225.  
  226.  
  227. - OGT_SetPosHandle
  228. - OGT_SetPosReference
  229. - OGT_SetDimReference   USHORT
  230.  
  231. Controllo fine della posizione e delle dimensioni di un oggetto.  Il loro uso
  232. interferisce con il significato da dare ai dati immessi con molti altri tag e
  233. quindi una spiegazione esclusivamente a parole risulterebbe troppo complicata e
  234. poco esplicativa.  Per essi si rimanda al programma demoPosition, che permette
  235. di comprendere in modo interattivo i concetti che stanno dietro a questi ed
  236. altri tag.
  237.  
  238.  
  239. - OGT_ScaleLeft
  240. - OGT_ScaleTop
  241. - OGT_ScaleWidth
  242. - OGT_ScaleHeight    UBYTE
  243.  
  244. Di default la posizione e le dimensioni di un oggetto si indicano come quantità
  245. assolute o comunque come quantità assolute da aggiungere ad altre quantità (vedi
  246. il caso di un oggetto relativo alle dimensioni del dominio).  Per permettere un
  247. maggior livello di libertà, si possono definire queste quantità come relative al
  248. font usato (OGT_FontRelative) o al dominio (OGT_DomainRelative).  Per esempio,
  249. un oggetto progettato per essere alto 14 con un font alto 8, verrà disegnato
  250. alto 28 con un font da 16.  Similmente un oggetto progettato per trovarsi a x=20
  251. in un dominio largo 100, in un dominio largo 300 si troverà a x=60.
  252.  
  253.  
  254. - OGT_FontXscale            default: 8
  255. - OGT_FontYscale            default: 8
  256. - OGT_DomainXscale          default: 100
  257. - OGT_DomainYscale   USHORT default: 100
  258.  
  259. Indicano i parametri con cui sono stati progettati gli oggetti.  C'è una caso
  260. particolare:  quando si pone Domain* = ~0, si indica che il loro valore è uguale
  261. a quello che si è specificato per le dimensioni della finestra.  Invece di
  262. scrivere:
  263.  
  264. --------------------------------------------------------------------------------
  265.    WA_InnerWidth   , 306,
  266.    WA_InnerHeight  , 120,
  267.    OGT_DomainXscale, 306,
  268.    OGT_DomainYscale, 120,
  269. --------------------------------------------------------------------------------
  270.  
  271. si può usare:
  272.  
  273. --------------------------------------------------------------------------------
  274.    WA_InnerWidth   , 306,
  275.    WA_InnerHeight  , 120,
  276.    OGT_DomainXscale, ~0 ,
  277.    OGT_DomainYscale, ~0 ,
  278. --------------------------------------------------------------------------------
  279.  
  280. Stessa cosa con WA_Width e WA_Height.
  281.  
  282.  
  283. - OGT_ResetAspect    void
  284.  
  285. Se un oggetto viene agganciato ad un gruppo, eredita da questo i parametri di
  286. progetto e le varie informazioni di scala.  Con questo tag si riportano ai
  287. valori di default tutti i campi, uno modo sintetico per dire:
  288.  
  289. --------------------------------------------------------------------------------
  290.   OGT_SetPosHandle   =OGT_X_Left     |OGT_Y_Top
  291.   OGT_SetPosReference=OGT_X_Left     |OGT_Y_Top
  292.   OGT_SetDimReference=OGT_X_Dim_Fixed|OGT_Y_Dim_Fixed
  293.   OGT_SetScaleLeft   =OGT_Fixed
  294.   OGT_SetScaleTop    =OGT_Fixed
  295.   OGT_SetScaleWidth  =OGT_Fixed
  296.   OGT_SetScaleHeight =OGT_Fixed
  297.   OGT_SetFontXscale  =8
  298.   OGT_SetFontYscale  =8
  299.   OGT_SetDomainXscale=100
  300.   OGT_SetDomainYscale=100
  301. --------------------------------------------------------------------------------
  302.  
  303.  
  304. - OGT_AlignToObject  Object *
  305.  
  306. Normalmente quando si indica un oggetto come allineato (Il concetto di
  307. allineamento è esplicitato nella documentazione del programma demoPosition) ad
  308. un altro oggetto ci si riferisce all'oggetto immediatamente precedente.  Con
  309. questo tag si può riferire l'allineamento a qualunque oggetto (naturalmente
  310. entrambe gli oggetti devono stare nello stesso dominio).
  311.  
  312.  
  313. - GA_Text            STRPTR
  314.  
  315. E' il testo che deve essere disegnato accanto ad un oggetto.  Viene copiato, non
  316. riferito.  Mettere un "_" nel testo indica che la lettera successiva deve essere
  317. risultare sottolineata e deve venir usata come short-cut per l'attivazione
  318. dell'oggetto.
  319.  
  320.  
  321. - OGT_TextFont       struct TextFont *
  322.  
  323. Font per GA_Text.
  324.  
  325.  
  326. - OGT_TextColor      SHORT
  327.  
  328. Colore per GA_Text.
  329.  
  330.  
  331. - OGT_TextPlacement  SHORT
  332.  
  333. Posizione del testo rispetto all'oggetto.  Può essere:
  334.  
  335.   OGT_Text_IN              dentro, centrato.
  336.   OGT_Text_IN_LEFTMOST     dentro, giustificato a sinistra.
  337.   OGT_Text_IN_RIGHTMOST    dentro, giustificato a destra.
  338.   OGT_Text_LEFT            a sinistra.
  339.   OGT_Text_RIGHT           a destra.
  340.   OGT_Text_ABOVE           sopra.
  341.   OGT_Text_BELOW           sotto.
  342.   OGT_Text_HIDE            invisibile, nel caso lo si voglia usare solo come
  343.                            abbreviazione da tastiera.
  344.  
  345. Il default dipende dall'oggetto.
  346.  
  347.  
  348. - OGT_DrawFrame
  349. - IA_Recessed
  350. - IA_DoubleEmboss
  351. - IA_EdgesOnly       BOOL
  352.  
  353. Modificano l'aspetto del bordo di un oggetto.
  354.  
  355.  
  356. - GA_Immediate
  357. - GA_FollowMouse
  358. - GA_RelVerify
  359. - OGT_ClickRepeat    BOOL
  360.  
  361. Servono per controllare la notifica di attivazione/disattivazione di un oggetto.
  362. Quando l'utente o l'applicazione attiva un oggetto, se GA_Immediate è TRUE,
  363. viene mandato fuori un messaggio di tipo OM_UPDATE contenente il tag
  364. OGT_GadgetDown, seguito ad emissioni di messaggi con tag OGT_GadgetRepeat ad
  365. intervalli di tempo regolari, nel caso in cui OGT_ClickRepeat sia TRUE.  I
  366. movimenti del mouse vengono seguiti attraverso l'uso del tag OGT_GadgetMove,
  367. filtrato da GA_FollowMouse.  Infine la disattivazione di un oggetto è comunicata
  368. per mezzo di OGT_GadgetUp, con filtro GA_RelVerify.  Tutti i vari OGT_Gadget*
  369. hanno in comune che viaggiano sempre in compagnia di altri due tag, OGT_ID e
  370. OGT_Object, in modo che sia sempre possibile identificare la sorgente del
  371. messaggio.  Per gli oggetti per cui ha senso un controllo sulla posizione del
  372. mouse vengono mandati fuori anche OGT_MouseX e OGT_MouseY, coordinate del mouse
  373. relative all'angolo dell'oggetto in alto a sinistra
  374.  
  375.  
  376. - OGT_Activation     ULONG
  377.  
  378. Serve per specificare i filtri precedenti in un solo colpo, per mezzo dei flag:
  379.  
  380.  + OGT_Act_ReportGadgetDown
  381.  + OGT_Act_ReportGadgetMove
  382.  + OGT_Act_ReportGadgetUp
  383.  + OGT_Act_ReportGadgetRepeat
  384.  + OGT_Act_ToggleType
  385.  
  386. L'ultimo serve solo per oggetti di classe BUTTON_OGT_CLASS, per indicare un
  387. funzionamento bistabile (modo attivabile anche per mezzo di GA_Selected).
  388.  
  389.  
  390. - OGT_AppGadget      BOOL
  391.  
  392. Se TRUE, indica che l'oggetto può ricevere notizia del rilascio di un'icona al
  393. suo interno, per mezzo del tag OGT_DroppedIcon.  Alcune classi lo mettono TRUE
  394. di default, altre capiscono direttamente un OGT_DroppedIcon e agiscono di
  395. conseguenza, altre ancora semplicemente passano oltre tutti i OGT_DroppedIcon
  396. ricevuti (questo è il comportamento di default).
  397.  
  398.  
  399. - OGT_DroppedIcon    STRPTR
  400.  
  401. E' un tag che viene mandato dalla libreria all'oggetto, nel caso che l'utente
  402. rilasci un'icona dentro il corpo dello stesso.  E' il nome completo di path
  403. dell'icona.  Se non c'è nessun oggetto sotto al mouse al momento del rilascio,
  404. tale tag è mandato direttamente all'applicazione.
  405.  
  406.  
  407. - OGT_AskedHelp      BOOL
  408.  
  409. Viene emesso da un oggetto, insieme agli altri tag esplicativi, quando viene
  410. richiesta una spiegazione del funzionamento dell'oggetto (l'utente ha premuto il
  411. tasto HELP sopra l'oggetto).
  412.  
  413.  
  414.  
  415. **GROUP_OGT_CLASS**
  416.  
  417. E' l'oggetto fondamentale di tutto il complesso.  Serve come raggruppatore di
  418. altri oggetti.  Può essere dotato di immagine (un bordo semplice o doppio) e di
  419. nome, oppure essere invisibile.  Altri oggetti possono essere aggregati ad esso
  420. per mezzo del metodo OM_ADDMEMBER e riferiranno poi la loro posizione e le loro
  421. dimensioni da esso.  Questo oggetto si occupa pure di liberare gli oggetti
  422. legati ad esso.  Se si manda un metodo OM_SET ad un gruppo, gli oggetti da esso
  423. legato riceveranno solo alcuni tag, gli altri, quelli che controllano posizione,
  424. dimensioni, in generale l'aspetto di un oggetto, verranno fermati.  Se si
  425. vogliono invece comunicare proprio quei cambiamenti di aspetto di un oggetto, si
  426. può operare in due modi:  o mandandoli direttamente ad esso, o mandandoli al
  427. gruppo a cui appartiene, con l'aggiunta di un tag GA_ID, con l'ID dell'oggetto
  428. che si vuole raggiungere.
  429.  
  430.  
  431.  
  432. **BUTTON_OGT_CLASS**
  433.  
  434. Classico button gadget, con la differenza che è possibile attivarlo anche per
  435. mezzo della funzione ActivateGadget.
  436.  
  437. - GA_Selected        BOOL
  438.  
  439. Rende il bottone bistabile, ne specifica il valore iniziale e, quando l'oggetto
  440. viene attivato, viene usato per comunicare il nuovo stato.  Se non viene
  441. specificato al momento della creazione dell'oggetto, viene usato nei messaggi
  442. emessi dal bottone, per indicare che il mouse è dentro (TRUE) o fuori (FALSE)
  443. dal corpo dell'oggetto.
  444.  
  445.  
  446. - OGTBU_Labels       STRPTR *
  447.  
  448. Un array di puntatori a stringa, terminato da NULL.  Questo tag modifica il
  449. funzionamento dell'oggetto da semplice bottone astabile a bottone ciclico.
  450. L'array è copiato, non referenziato.
  451.  
  452.  
  453. - OGTBU_ActiveLabel  SHORT
  454.  
  455. Nel caso di un bottone ciclico, è l'elemento che deve risultare attivo
  456. all'inizio.  Tale tag viene anche emesso dall'oggetto per indicare un
  457. cambiamento di stato (l'utente ha selezionato un altra stringa o l'applicazione
  458. ha aggiornato l'oggetto).  Se OGT_ClickRepeat è TRUE, attivando il bottone si
  459. possono scorrere tutte le stringhe senza doverle selezionare a una a una.  In
  460. ogni caso il resto del sistema non viene informato del cambiamento di stato se
  461. non al rilascio del bottone, sempre che il mouse sia ancora sull'oggetto.
  462. Premere il tasto destro del mouse ha la funzione di un UNDO.
  463.  
  464. - OGTBU_VectorImageDef  SHORT
  465. - OGTBU_VectorImage     struct OGT_VectorImage *
  466.  
  467.  
  468.  
  469. **STRING_OGT_CLASS**
  470.  
  471. Le istanze di questa classe sono i classici "string gadget", con il vantaggio
  472. che tutti i buffer sono gestiti dall'oggetto, cioè non è necessaria alcuna
  473. allocazione di buffer da parte dell'applicazione.  Essendo una sottoclasse della
  474. classe STRGCLASS (in realtà è figlia sia di quella classe che di una classe
  475. privata della libreria, costituendo così un esempio di ereditarietà multipla),
  476. ne eredita tutti i settaggi, con alcune differenze di funzionamento.  Con
  477. STRINGA_EXITHELP, se l'utente preme il tasto HELP, l'oggetto emette un
  478. OGT_AskedHelp e rimette a posto il valore dell'oggetto.  Questa è la differenza
  479. più importante rispetto a tutti gli altri string gadget:  l'oggetto non rimane
  480. mai in uno stato inconsistente con il resto del sistema, cioè il dato immesso
  481. dall'utente non è accettato se non è completo.  Se l'oggetto si disattiva,
  482. perchè un'altra finestra è divenuta attiva, perchè l'utente ha premuto il tasto
  483. destro del mouse, perchè ha attivato un'altro oggetto o infine perchè ha chiesto
  484. un aiuto per mezzo del tasto HELP, l'oggetto effettua un UNDO, in modo che vi
  485. sia sempre coerenza fra quello che è visualizzato dall'oggetto e quello che il
  486. resto del sistema crede vi sia visualizzato.  Come tutti gli string gadget, può
  487. essere sia di tipo TEXT che di tipo LONG.  Nel primo caso, specificando il tag
  488. OGT_AppGadget, accetta come input pure il rilascio di un'icona.
  489.  
  490.  
  491.  
  492. **PROP_OGT_CLASS**
  493.  
  494. - PGA_Pos
  495. - PGA_Total
  496. - PGA_Visible        ULONG
  497.  
  498. Sono rispettivamente il livello iniziale, il numero totale di livelli e il
  499. numero di livelli visibili.  Contrariamente a tutti gli altri gadget
  500. proporzionali, gli oggetti di questa classe hanno 32 bit di risoluzione.  Tutti
  501. questi tag vengono emessi dall'oggetto, se modificato.  Se è presente uno
  502. short-cut, senza SHIFT aumenta il valore di PGA_Top, con SHIFT lo diminuisce.
  503.  
  504.  
  505. - PGA_Freedom        FREEVERT o FREEHORIZ
  506.  
  507. Il tipo di movimento, verticale od orizzontale.
  508.  
  509.  
  510. - PGA_NewLook        BOOL
  511.  
  512. Se TRUE assume un aspetto diverso, uguale a quello dei gadget usati dal
  513. Workbench.
  514.  
  515.  
  516.  
  517. **SCROLLER_OGT_CLASS**
  518.  
  519. Questa è una classe derivata dalla classe PROP_OGT_CLASS, ne condivide quindi
  520. tutte le funzionalità, con l'unica differenza della presenza di due bottoni, per
  521. andare avanti o indietro di un livello.  Se tenuti premuti, i bottoni continuano
  522. a muovere di un livello.
  523.  
  524. - OGTSR_ArrowSize    USHORT default: 16
  525.  
  526. Larghezza (se FREEHORIZ) o altezza (se FREEVERT) dei bottoni.
  527.  
  528.  
  529.  
  530. **MULTIWAY_OGT_CLASS**
  531.  
  532. Le istanze di questa classe permettono di scegliere una voce fra tante o un
  533. insieme di voci.  A seconda del tipo di funzionamento, che può essere modificato
  534. per mezzo dei tag OGTMW_ActiveLabel e OGTMW_ActiveMask, cambia automaticamente
  535. l'aspetto con cui viene reso.  Il modo di default è quello inclusivo (un insieme
  536. di voci).  Se non vengono specificate le dimensioni dell'oggetto, esse si
  537. adatteranno al numero di voci e al tipo di funzionamento.  Se invece si
  538. specifica la larghezza e/o l'altezza dell'oggetto, saranno gli elementi di
  539. selezione delle voci a ridimensionarsi.
  540.  
  541. - OGTMW_Labels       STRPTR *
  542.  
  543. Un array di puntatori a stringa, terminato da NULL.  E' l'insieme delle scelte
  544. possibili, dove ogni stringa corrisponde ad un bottone e può essere dotata di
  545. short-cut.  Nel caso questo tag non fosse specificato o il suo valore fosse
  546. NULL, il funzionamento dell'oggetto è quello di un bottone bistabile, reso
  547. graficamente con un Check Mark e il cui testo è specificato da GA_Text.  In
  548. tutti gli altri casi GA_Text è semplicemente il titolo da dare all'insieme delle
  549. scelte.  L'array è copiato, non referenziato.
  550.  
  551.  
  552. - OGTMW_ActiveLabel  SHORT
  553.  
  554. Attiva il modo esclusivo (una voce fra tante), ed indica l'elemento attivo.  Lo
  555. stesso tag viene emesso nel caso di una modificazione dello stato dell'oggetto.
  556.  
  557.  
  558. - OGTMW_ActiveMask   ULONG
  559.  
  560. Attiva il modo inclusivo, ed ogni suo bit indica lo stato della corrispondente
  561. voce (bit 0 per la 1^ voce, etc.  etc.  ).  Lo stesso tag viene emesso nel caso
  562. di una modificazione dello stato dell'oggetto.
  563.  
  564.  
  565.  
  566. **LISTVIEW_OGT_CLASS**
  567.  
  568. Oggetto simile alla LISTVIEW_KIND della GadTools, serve per mostrare liste di
  569. nomi, contrariamente ad esso si crea una copia privata dei nomi, permettendo
  570. così anche l'uso di array di nomi, oltre che di liste.  La lista rimane di
  571. proprietà dell'oggetto, che può cederla ad altri solo in lettura.  Per
  572. modificare la lista ci sono degli appositi tag, che effettuano le normali
  573. operazioni possibile su una lista (inserimento, rimozione, modifica).  Sempre
  574. l'oggetto può gestire un campo per l'evidenziazione del valore selezionato o per
  575. il suo editing, con uno string gadget.  In quest'ultimo caso è gestito pure
  576. dall'oggetto l'aggiornamento della lista con il nuovo nome.  Se è necessario un
  577. editing particolare, è possibile installare una propria routine di editing, con
  578. il tag STRINGA_EditHook.
  579.  
  580. Se dotato di short-cut, risponde spostandosi di una posizione in alto o in
  581. basso, a seconda che sia con o senza SHIFT.
  582.  
  583. - OGTLV_Labels       STRPTR *
  584. - OGTLV_ListOfLabels struct MinList *
  585.  
  586. Sono i due tag usati per immettere la lista dei nomi.  Il primo caso è il più
  587. semplice, un array di puntatori a stringa.  Il secondo consiste in una lista di
  588. strutture di tipo Node, con il nome nel campo ln_Name.  In entrambi i casi i
  589. nomi sono copiati, non referenziati.
  590.  
  591.  
  592. - OGTLV_ActiveLabel  LONG
  593.  
  594. E' la posizione del nome attivo.  Oltre a fornire lo stato iniziale, viene
  595. emesso dall'oggetto stesso quando l'utente o l'applicazione seleziona un nome.
  596.  
  597.  
  598. - OGTLV_FontOfLabels struct TextFont *
  599.  
  600. Il font da usare per i nomi.
  601.  
  602.  
  603. - OGTLV_ReadOnly
  604. - OGTLV_ShowSelected BOOL
  605.  
  606. Attivano rispettivamente il campo di visualizzazione o quello di editing.  Il
  607. primo ha la priorità sul secondo.
  608.  
  609.  
  610. - OGTLV_ToggleSelect BOOL
  611.  
  612. Normalmente quando l'utente seleziona una voce, l'oggetto emette un
  613. OGTLV_ActiveLabel al rilascio del bottone del mouse, con il numero della voce
  614. selezionata.  Se questo tag è TRUE invece l'oggetto cambia subito di stato la
  615. voce selezionata ed emette sia ActiveLabel che GA_Selected, il nuovo stato della
  616. voce (Se si legge direttamente la lista delle voci, una voce selezionata è
  617. marcata con il flag ReverseColors).
  618.  
  619.  
  620. - OGTLV_Top             LONG
  621. - OGTLV_FollowSelected  BOOL
  622.  
  623. Controllano la posizione della finestra di visibilità dei nomi.  Con OGTLV_Top
  624. si comunica una posizione precisa, da mostrare adesso, mentre con l'altro si
  625. chiede di operare in modo da rendere visibile il nome selezionato, ogni
  626. qualvolta questo venga cambiato per mezzo di OGTLV_ActiveLabel.
  627.  
  628.  
  629. - OGTLV_Spacing      ULONG
  630.  
  631. Spazio extra fra un nome e l'altro, normalmente 0.
  632.  
  633.  
  634. - OGTLV_ScrollWidth  ULONG
  635.  
  636. Larghezza dell'elemento di scroll di destra, normalmente 16.
  637.  
  638.  
  639. - OGTLV_ShowHeight   ULONG
  640.  
  641. Altezza del campo di visualizzazione/editing.  Normalmente 6 pixel più alto del
  642. font usato.
  643.  
  644.  
  645. - OGTLV_LockList     BOOL
  646.  
  647. Serve per bloccare ogni visualizzazione della lista, nel caso si vogliano fare
  648. modifiche e non si desideri mostrare il risultato intermedio.
  649.  
  650.  
  651. - OGTLV_WorkLabelPos LONG
  652.  
  653. Indica la posizione nella lista del nome da manipolare (vedi sotto).  Se non
  654. viene specificato, il default è la posizione del nome attivo.
  655.  
  656.  
  657. - OGTLV_InsertLabelBefore
  658. - OGTLV_InsertLabelAfter
  659. - OGTLV_DeleteLabel
  660. - OGTLV_ChangeLabel        STRPTR
  661.  
  662. Metodi per manipolare la lista dei nomi.  InsertLabelBefore e InsertLabelAfter
  663. aggiungono un nome, rispettivamente prima e dopo quello indicato, DeleteLabel lo
  664. cancella e ChangeLabel lo modifica.  Quest'ultimo, congiuntamente a
  665. OGTLV_ActiveLabel, viene emesso dall'oggetto per comunicare che l'utente ha
  666. modificato un nome della lista.
  667.  
  668.  
  669.  
  670. **ASLREQ_OGT_CLASS**
  671.  
  672. E' un oggetto di tipo nuovo:  un ASL requester.  Il suo aspetto può essere
  673. quello di un bottone, con disegnata una cartelletta, nel caso più elementare, a
  674. cui si possono affiancare uno o due string gadget.  Accetta tutti i tag della
  675. "asl.library".  Di default è anche un AppGadget, cioè accetta come input il
  676. rilascio di un'icona.
  677.  
  678. - OGTAR_Type         SHORT
  679.  
  680. Specifica se si tratta di un file requester (dato = ASL_FileRequest) o un font
  681. requester (dato = ASL_FontRequest).
  682.  
  683.  
  684. - OGTAR_ShowSelected BOOL
  685.  
  686. Se TRUE aggiunge uno (nel caso del file requester) o due string gadget (nel caso
  687. del font requester).  Se invece il file requester è del tipo a selezione
  688. multipla, questo tag è ignorato.
  689.  
  690.  
  691. - ASL_File
  692. - ASL_Dir
  693. - OGTAR_FullFileName STRPTR
  694.  
  695. Indicano la situazione iniziale del requester e vengono anche usati per
  696. comunicare le scelte fatte.
  697.  
  698.  
  699. - OGTAR_FilesSelected   STRPTR *
  700.  
  701. Un array, terminato da un NULL, di puntatori a stringa.  Viene comunicato solo
  702. nel caso di un file requester a scelta multipla.
  703.  
  704.  
  705. - ASL_FontName       STRPTR
  706. - ASL_FontHeight     SHORT
  707. - OGTAR_FontData     struct TextAttr *
  708.  
  709. Sono gli equivalenti di ASL_File, ASL_Dir e OGTAR_FullFileName per il font
  710. requester.
  711.  
  712.  
  713.  
  714. **SHOWTEXT_OGT_CLASS**
  715.  
  716. Questo oggetto serve solo per mostrare dei risultati, non consente alcun input
  717. da utente e non emette alcun output.
  718.  
  719. - OGTST_Number       LONG
  720. - OGTST_Label        STRPTR
  721. - OGTST_Labels       STRPTR *
  722. - OGTST_Format       STRPTR
  723. - OGTST_Arguments    void **
  724.  
  725. Sono i vari tipi di dato che l'oggetto può visualizzare:  semplice numero
  726. (Number), semplice stringa (Label), array di stringhe (Labels) e testo
  727. formattato (Format e Arguments).  Comunque tutti i tipi di dato vengono
  728. trasformati in un'unica stringa prima di disegnarli.  Il testo può essere anche
  729. su più linee, basta aggiungere un newline ('\n'), tenendo presente che nel caso
  730. di Labels tale newline è già inserito fra le varie linee.  Inoltre l'oggetto
  731. riconosce altre sequenze di controllo, per modificare l'aspetto del testo:
  732. '\x01\x<n>' cambia il colore usato in <n>, '\x02' attiva il modo sottolineato,
  733. '\x03' il neretto e '\x04' l'italico.  Tali modifiche hanno valore sono su una
  734. linea e interessano tutta la linea.  Il default è OGTST_Number.
  735.  
  736.  
  737. - OGTST_Placement    SHORT
  738.  
  739. Specifica il tipo di giustificazione orizzontale e verticale da usare.  Quella
  740. orizzontale è controllata tramite:
  741.  
  742.   OGT_X_Left
  743.   OGT_X_Center
  744.   OGT_X_Right
  745.  
  746. mentre quella verticale da:
  747.  
  748.   OGT_Y_Top
  749.   OGT_Y_Center
  750.   OGT_Y_Bottom
  751.  
  752. Normalmente il testo viene centrato rispetto all'oggetto (OGT_X_Center +
  753. OGT_Y_Center).
  754.  
  755.  
  756.  
  757. **SHOWLIST_OGT_CLASS**
  758.  
  759. E' un nuovo oggetto, che serve come versatile visualizzatore di testi (e volendo
  760. anche grafica:  un esempio di lista mista di testo e grafica si ha nel programma
  761. demoGfx).  Viene presentato dopo LISTVIEW_OGT_CLASS ma solo perchè è più
  762. complesso.  Infatti un oggetto della classe LISTVIEW_OGT_CLASS è un gruppo di
  763. oggetti, formato mettendo insieme oggetti delle classi SCROLLER_OGT_CLASS,
  764. SHOWLIST_OGT_CLASS, SHOWTEXT_OGT_CLASS o STRING_OGT_CLASS, solo che le
  765. applicazioni non se ne rendono conto.
  766.  
  767. - OGTSL_Labels             STRPTR *
  768. - OGTSL_ListOfLabels       struct MinList *
  769. - OGTSL_FileToLoadByFH     BPTR
  770. - OGTSL_FileToLoadByName   STRPTR
  771.  
  772. Sono i tag usati per immettere il testo.  Il primo caso è il più semplice, un
  773. array di puntatori a stringa.  Il secondo consiste in una lista di strutture di
  774. tipo Node, con la stringa nel campo ln_Name.  Gli ultimi due tag indicano che il
  775. testo è contenuto in un file, di cui si passa o l'handle o il nome.  Sarà cura
  776. dell'oggetto leggersi il file per trasformarlo in una lista di linee di testo.
  777. Ci sono volte in cui è desiderabile mostrare qualcosa che non sia già in forma
  778. di testo.  Ciò si può fare usando il tag ListOfLabels in combinazione del tag
  779. OGTSL_TranslateLabel:  i campi ln_Name non vengono più considerati stringhe ma
  780. semplici puntatori a dati, che sarà cura dell'applicazione trasformare in testo
  781. al momento della visualizzazione, con il meccanismo del call-back attraverso
  782. TranslateLabel.  Salvo nel caso precedente, tutte le stringhe vengono copiate,
  783. non referenziate.
  784.  
  785.  
  786. - OGTSL_TranslateLabel  struct Hook *
  787.  
  788. Come già accennato, viene usato per trasformare in testo i dati puntati dal
  789. campo ln_Name dei nodi della lista dell'oggetto.  L'Hook viene chiamato con un
  790. messaggio che ha questa struttura:
  791.  
  792. --------------------------------------------------------------------------------
  793. struct ogmsl_Translate
  794. {
  795.    struct ogmsl_Node *ogmsl_Node;
  796.    STRPTR             ogmsl_Text;
  797.    LONG               ogmsl_TextLength;
  798. };
  799. --------------------------------------------------------------------------------
  800.  
  801. con i campo Text e TextLength inizializzati con NULL e -1.  L'applicazione deve
  802. ritornare il messaggio con il testo puntato da Text e se necessario la sua
  803. lunghezza in TextLength (se si lascia un valore negativo in questo campo, sarà
  804. l'oggetto a calcolare la lunghezza della stringa).
  805.  
  806. All'interno  dell'Hook  si  possono  anche  cambiare  gli attributi della linea,
  807. manipolando alcuni campi della struttura ogmsl_Node:
  808.  
  809. --------------------------------------------------------------------------------
  810. struct ogmsl_Node
  811. {
  812.    struct Node ogmsl_Data;
  813.    SHORT       ogmsl_Flags;
  814. };
  815.  
  816. #define ogmsl_Flags_ReverseColors ...
  817. #define ogmsl_Flags_UsePriAsColor ...
  818. --------------------------------------------------------------------------------
  819.  
  820. "ReverseColors" inverte il colore del testo e dello sfondo, in modo da rendere
  821. l'effetto della selezione.
  822. "UsePriAsColor" invece indica che il colore per il testo è contenuto nel campo
  823. ln_Pri del nodo.
  824.  
  825. E' importante ricordare che l'oggetto, non appena incontra questo tag, libera
  826. ogni testo precedente.  Questo comporta che una lista di tag del tipo:
  827.  
  828. --------------------------------------------------------------------------------
  829.    { OGTSL_ListOfLabels  , .... }
  830.    { OGTSL_TranslateLabel, ...  }
  831. --------------------------------------------------------------------------------
  832.  
  833. ha come risultato finale una cosa diversa da:
  834.  
  835. --------------------------------------------------------------------------------
  836.    { OGTSL_TranslateLabel, ...  }
  837.    { OGTSL_ListOfLabels  , .... }
  838. --------------------------------------------------------------------------------
  839.  
  840. Naturalmente la seconda è quella corretta.
  841.  
  842.  
  843. - OGTSL_FontOfLabels struct TextFont *
  844.  
  845. Il font da usare per i nomi.
  846.  
  847.  
  848. - OGTSL_LockList           BOOL
  849. - OGTSL_WorkLabelPos       LONG
  850. - OGTSL_InsertLabelBefore  STRPTR
  851. - OGTSL_InsertLabelAfter   STRPTR
  852. - OGTSL_DeleteLabel        STRPTR
  853. - OGTSL_ChangeLabel        STRPTR
  854.  
  855. Svolgono le stesse funzioni dei loro quasi-omonimi della classe
  856. LISTVIEW_OGT_CLASS.
  857.  
  858.  
  859. - OGTSL_Freedom      ULONG
  860.  
  861. Specifica il grado di libertà dei movimenti del testo.  Si può scorrere il testo
  862. sia orizzontalmente che verticalmente che in entrambe i modi.  Usa gli stessi
  863. dati di PGA_Freedom.  Il default è per un movimento bidimensionale.
  864.  
  865. - OGTSL_VertPos
  866. - OGTSL_VertTotal
  867. - OGTSL_VertVisible  LONG
  868.  
  869. Posizione, dimensione e visibilità verticale del testo.  Total e Visible vengono
  870. calcolati in modo automatico dall'oggetto, ma si può sempre modificare il valore
  871. di Total (non ha senso invece modificare il valore di Visible).  Questi tag sono
  872. pure emessi dall'oggetto per indicare un cambiamento nello stato dell'oggetto.
  873.  
  874.  
  875. - OGTSL_HoriPos
  876. - OGTSL_HoriTotal
  877. - OGTSL_HoriVisible  LONG
  878.  
  879. Lo controparti orizzontali del tag precedenti.
  880.  
  881.  
  882. - OGTSL_UseNumPad    BOOL
  883.  
  884. Se TRUE, oltre allo short-cut usuale, l'oggetto fa uso del tastierino numerico,
  885. secondo il significato dei tasti ("Home", "Page Up", etc.  etc.  ).
  886.  
  887.  
  888. - OGTSL_Spacing      ULONG
  889.  
  890. Spazio extra fra le linee (default 0).
  891.  
  892.  
  893. - OGTSL_HitX                  LONG
  894. - OGTSL_HitY                  LONG
  895. - OGTSL_HitLabelNumFromList   LONG
  896. - OGTSL_HitLabelFromList      struct ogmsl_Node *
  897.  
  898. Sono tag emessi dall'oggetto quando l'utente lo attiva.  HitX e HitY sono le
  899. coordinate del mouse relative all'oggetto, ma espresse in termini di caratteri,
  900. non di pixel, in pratica HitX = MouseX / FontXsize.  Gli altri sono un puntatore
  901. alla struttura ogmsl_Node della linea di testo selezionata e la sua posizione
  902. nella lista delle linee di testo.  Altro tag significativo è GA_Selected, che
  903. indica se il mouse è dentro TRUE o fuori FALSE dell'oggetto.  In risposta ad
  904. un'attivazione da parte dell'utente, l'oggetto emette sempre un messaggio, anche
  905. se il mouse non si trova sopra una linea di testo, ponendo però HitLabelFromList
  906. = NULL.
  907.  
  908.  
  909.  
  910. - OGTSL_ExtraRendering  struct Hook *
  911.  
  912. E' un Hook usato per aggiungere altro rendering oltre al semplice testo.  Se
  913. presente, viene chiamato due volte, prima di disegnare il testo (AfterText =
  914. FALSE) e dopo (AfterText = TRUE).  Il messaggio che gli viene passato è:
  915.  
  916. --------------------------------------------------------------------------------
  917. struct ogmsl_ExtraRendering
  918. {
  919.    struct MinList    *ogmsl_Nodes;
  920.    struct ogmsl_Node *ogmsl_FirstNode;
  921.    struct RastPort   *ogmsl_RPort;
  922.    struct IBox        ogmsl_Domain;
  923.    ULONG              ogmsl_TextScrollLeft;
  924.    ULONG              ogmsl_TextScrollTop;
  925.    ULONG              ogmsl_TextSpacing;
  926.    BOOL               ogmsl_AfterText;
  927. };
  928. --------------------------------------------------------------------------------
  929.  
  930. La finestra "fisica" dove effettuare il rendering è specificata per mezzo del
  931. rettangolo Domain, mentra la finestra "virtuale", con le stesse dimensioni, è
  932. invece posizionata a (TextScrollLeft, TextScrollTop).  E' quindi necessario fare
  933. una traslazione del sistema di coordinate prima di disegnare, mediante la
  934. trasformazione:
  935.  
  936. --------------------------------------------------------------------------------
  937. X = x + ogmsl_Domain.Left - ogmsl_TextScrollLeft
  938. Y = y + ogmsl_Domain.Top  - ogmsl_TextScrollTop
  939. --------------------------------------------------------------------------------
  940.  
  941. Non è necessario invece preoccuparsi del clipping, l'oggetto ha già installato
  942. una ClipRegion.  FirstNode è un puntatore alla prima linea di testo che si vede
  943. tramite Domain e TextSpacing è l'altezza in pixel di ogni linea.
  944.  
  945.  
  946.  
  947. **MENU_OGT_CLASS**
  948.  
  949. E siamo arrivati all'ultima classe, la classe dei menus.  Per rendere più
  950. agevole la sua gestione si è pensato di differenziarla dalle altre.  Gli oggetti
  951. istanziati da una classe normale sono del tutto indipendenti gli uni dagli
  952. altri, soprattutto nei dati, mentre qui creare un oggetto menu equivale a
  953. richiedere un handle per l'accesso alla struttura dei menu di una finestra,
  954. cosicchè è possibile creare più di un oggetto ma tutti si riferiscono agli
  955. stessi dati.  Anche il modo di definire un oggetto menu è differente:  i menu
  956. non sono altro che un albero e quindi è conveniente seguire questa topologia.
  957. Allora i nodi al primo livello saranno i menu, quelli al secondo gli item ed
  958. infine al terzo livello si troveranno gli eventuali subitem.  Per poi modificare
  959. un elemento non si farà altro che specificare il percorso per raggiungerlo lungo
  960. l'albero e poi i dati da modificare.
  961.  
  962. - OGTMN_Menu         STRPTR
  963. - OGTMN_Item         STRPTR
  964. - OGTMN_ImageItem    struct Image *
  965. - OGTMN_SubItem      STRPTR
  966. - OGTMN_ImageSubItem struct Image *
  967. - OGTMN_BarLabel     void
  968.  
  969. Permettono sia la creazione che la manutenzione della struttura dei menu.
  970. All'inizio ci si trova sulla radice dell'albero.  Specificando Menu, ci si
  971. sposta sul menu specificato, dopo averlo creato nel caso questo non esista.
  972. Stessa cosa per Item e SubItem.  Con BarLabel si aggiunge un semplice
  973. separatore, mentre gli Image dicono di usare immagini al posto di nomi.  Ad
  974. esempio, per creare una struttura come:
  975.  
  976. --------------------------------------------------------------------------------
  977. Project        Edit
  978.  Load           Mark
  979.  Save           Copy
  980.  Save as        Cut
  981.  Export         Paste
  982.   ASCII
  983.   IFF
  984.  About
  985.  Quit
  986. --------------------------------------------------------------------------------
  987.  
  988. si fornirà una taglist del tipo:
  989.  
  990. --------------------------------------------------------------------------------
  991.  OGTMN_Menu   , "Project",
  992.  OGTMN_Item   , "Load"   ,
  993.  OGTMN_Item   , "Save"   ,
  994.  OGTMN_Item   , "Save as",
  995.  OGTMN_Item   , "Export" ,
  996.  OGTMN_SubItem, "ASCII"  ,
  997.  OGTMN_SubItem, "IFF"    ,
  998.  OGTMN_Item   , "About"  ,
  999.  OGTMN_Item   , "Quit"   ,
  1000.  OGTMN_Menu   , "Edit"   ,
  1001.  OGTMN_Item   , "Mark"   ,
  1002.  OGTMN_Item   , "Copy"   ,
  1003.  OGTMN_Item   , "Cut"    ,
  1004.  OGTMN_Item   , "Paste"  ,
  1005.  TAG_DONE
  1006. --------------------------------------------------------------------------------
  1007.  
  1008.  
  1009. - OGTMN_NewName      STRPTR
  1010.  
  1011. Cambia il nome del nodo corrente. Ad esempio:
  1012.  
  1013. --------------------------------------------------------------------------------
  1014.  OGTMN_Menu   , "Project",
  1015.  OGTMN_Item   , "Load"   ,
  1016.  OGTMN_NewName, "Carica"
  1017.  TAG_DONE
  1018. --------------------------------------------------------------------------------
  1019.  
  1020. cambia in "Carica" il nome dell'item "Load" nel menu "Project".
  1021.  
  1022.  
  1023. - OGTMN_ShortCut     SHORT
  1024.  
  1025. Short-cut per il nodo corrente.
  1026.  
  1027.  
  1028. - GA_Selected           BOOL
  1029. - OGTMN_MutualExclude   ULONG
  1030.  
  1031. Controllano gli item di tipo bistabile.  Il primo indica lo stato, mentre il
  1032. secondo indica quali sono gli item da resettare se l'item corrente viene
  1033. selezionato.
  1034.  
  1035. - OGTMN_ClearMenus   BOOL
  1036.  
  1037. Se FALSE cancella tutti gli elementi attaccati al nodo corrente, mentre TRUE
  1038. cancella pure il nodo corrente, spostandosi sul nodo padre.  Usato come primo
  1039. tag cancella tutta la struttura dei menu.
  1040.  
  1041.  
  1042. - OGTMN_MenuStrip    struct Menu *
  1043.  
  1044. Ritorna il puntatore alla struttura dei menu.
  1045.  
  1046.  
  1047. - OGTMN_MenuUp
  1048. - OGTMN_MenuItemUp
  1049. - OGTMN_MenuSubItemUp   ULONG
  1050.  
  1051. Vengono emessi quando un elemento è stato selezionato.  Possono essere emessi
  1052. tutti per indicare che è stato selezionato un subitem, solo i primi due per un
  1053. item, o solo MenuUp per la selezione di un menu (possibile quando si preme HELP,
  1054. per avere un aiuto).  Come per gli altri oggetti, se è presente anche il tag
  1055. OGT_AskedHelp, si tratta di una richiesta di aiuto, non un'azione vera e
  1056. propria.  Per gli item bistabile è emesso pure lo stato, per mezzo di
  1057. GA_Selected.
  1058.  
  1059.  
  1060. - OGTMN_Hook         struct Hook *
  1061.  
  1062. Se l'item viene selezionato, oltre ad emettere il solito messaggio di tipo
  1063. OM_UPDATE, l'oggetto chiama la funzione specificata con la stessa taglist come
  1064. messaggio.
  1065.  
  1066.  
  1067.  
  1068. *Descrizione delle funzioni*
  1069.  
  1070. Come per la GadTools, le classi hanno bisogno di avere informazioni circa
  1071. l'ambiente in cui devono disegnare gli oggetti.  Tutti questi dati sono
  1072. contenuti in una struttura privata, che viene allocata tramite la chiamata alla
  1073. funzione OGT_GetVisualInfoA (esiste anche una OGT_GetVisualInfo, con argomenti
  1074. sullo stack).  Come già detto nella descrizione dei tag, la funzione ritorna un
  1075. puntatore, che dovrà essere ripassato alla libreria per la creazione degli
  1076. oggetti, per mezzo del tag OGT_VisualInfo.  Diversamente dalla GadTools, è la
  1077. libreria che si occupa di aprire e chiudere la finestra.  I settaggi per la
  1078. finestra sono passati proprio alla OGT_GetVisualInfoA, che li copierà e adatterà
  1079. alle proprio esigenze.  Abbiamo detto "adatterà" e vediamo perchè.  Oltre ai tag
  1080. per definire le caratteristiche della finestra, alla funzione si passano pure
  1081. altri tag, alcuni già visti, come:
  1082.  
  1083. --------------------------------------------------------------------------------
  1084.      OGT_TextFont
  1085.      OGT_ScaleLeft
  1086.      OGT_ScaleTop
  1087.      OGT_ScaleWidth
  1088.      OGT_ScaleHeight
  1089.      OGT_FontXscale
  1090.      OGT_FontYscale
  1091.      OGT_DomainXscale
  1092.      OGT_DomainYscale
  1093. --------------------------------------------------------------------------------
  1094.  
  1095. che definiscono i parametri di progetto comuni a tutti gli oggetti.  Alla
  1096. creazione un oggetto eredita da suo padre i parametri di progetto e se l'oggetto
  1097. non ha per padre un altro oggetto, eredita quelli definiti per mezzo di questa
  1098. funzione.  Ci sono altri tre tag, specifici di questa funzione:
  1099.  
  1100. - OVI_GimmeZeroZero  BOOL
  1101.  
  1102. Definisce la finestra come GimmeZeroZero, però la gestisce in modo diverso
  1103. rispetto ad una normale finestra di questo tipo:  nessuna seconda RastPort, sono
  1104. gli oggetti che si adattano.
  1105.  
  1106.  
  1107. - OVI_AdaptWidthToFont
  1108. - OVI_AdaptHeightToFont BOOL
  1109.  
  1110. Questi tag giustificano l' "adatterà" usato prima.  Indicano che le dimensioni e
  1111. eventualmente la posizione della finestra devono essere adattate al font usato,
  1112. che può essere quello di default o uno specificato dall'applicazione, per mezzo
  1113. di OGT_TextFont.  L'algoritmo è abbastanza "smart" per gestire situazioni in cui
  1114. il font specificato sia troppo grande per permette alla finestra di stare nei
  1115. limiti dello schermo, adottando, fra le altezze disponibili, la più grande che
  1116. permetta di rispettare tali limiti, riconoscendo inoltre i font scalabili e
  1117. creandoli della dimensione necessaria.  Se proprio non riesce a trovare niente
  1118. con il font specificato, effettua un ultimo tentativo con il font topaz e poi
  1119. esce con un errore.  Per adattarsi alle dimensioni del font usa i valori del
  1120. font di progetto, specificati per mezzo di Font*Scale, o il default (vedi
  1121. OGT_ResetAspect).
  1122.  
  1123. L'adattamento funziona sia con finestre definite per mezzo delle dimensioni
  1124. esterne che per mezzo delle dimensioni interne.  Da ultimo adatta pure i valori
  1125. per le dimensioni massime e minime della finestra e quelli di un eventuale tag
  1126. WA_Zoom, copiando la struttura, non modificando quella originale.
  1127.  
  1128.  
  1129. Un'ultima cosa su questa funzione:  oltre ai tag si può passare un puntatore ad
  1130. una MsgPort definita dall'applicazione, cosa utile se si usano molte finestre.
  1131. La libreria non ha problemi se la MsgPort è usata per più finestre o anche per
  1132. altri usi, l'importante è che si usi la funzione Wait per aspettare messaggi,
  1133. non WaitPort.  Il motivo di questa stranezza è dovuto all'implementazione della
  1134. libreria.  Ogni finestra gestita dalla libreria è anche una AppWindow, che
  1135. necessita di una porta messaggi separata dove ricevere i dati dal Workbench,
  1136. quindi i messaggi per la finestra arrivano da due sorgenti, l'input.device e il
  1137. Workbench, su due MsgPort distinte.  Con WaitPort si aspetta solo su una porta
  1138. per volta, di cui la necessità di aspettare un segnale piuttosto che un
  1139. messaggio.
  1140.  
  1141. Per creare gli oggetti non è necessaria una funzione speciale, come la
  1142. CreateGadget della GadTools, basta la NewObject di Intuition.  Per motivi di
  1143. praticità è conveniente però usare la OGT_BuildObjects della OGT.  E' poco più
  1144. di una versione multipla di NewObject, in quanto crea più oggetti in una sola
  1145. volta, il "poco più" è che apre anche la finestra, dopo aver creato gli oggetti.
  1146. Può sembrare poco utile, ma creando più oggetti insieme permette una maggior
  1147. semplicità nel definirli, evitando i problemi descritti nel seguito.
  1148.  
  1149. Abbiamo già parlato del fatto che gli oggetti comunicano fra loro per mezzo di
  1150. messaggi, che possono essere raggruppati dentro un altro oggetto, che possono
  1151. essere allineati gli uni agli altri.  Tutto chiaro, fino al momento in cui si
  1152. devono costruire gli oggetti, perchè quelle relazioni sono definite per mezzo di
  1153. puntatori ad oggetti ed è quindi necessario costruire l'oggetto riferito prima
  1154. di quello riferente.  Nella costruzione di una rete di oggetti i cicli sono
  1155. molto frequenti e quindi il caso in cui A e B siano allo stesso tempo riferito e
  1156. riferente l'uno dell'altro non permette di costruire la rete con solo chiamate a
  1157. NewObject.
  1158.  
  1159. Come si è visto non basta costruire gli oggetti, bisogna pure costruirli in una
  1160. certa sequenza, che varia da caso a caso.  La OGT_BuildObjects permette di
  1161. dimenticare totalmente tutti questi problemi.  Anzitutto divide nettamente la
  1162. definizione dei rapporti geometrici fra gli oggetti da quella dei rapporti di
  1163. comunicazione fra gli stessi.  Poi i rapporti, di ogni tipo, li descrive per
  1164. mezzo di numeri e non di puntatori ("oggetto 1 allineato con oggetto 2",
  1165. "oggetto 5 comunica con oggetto 3").  Vediamo nei dettagli come funziona.  Il
  1166. prototype è:
  1167.  
  1168. --------------------------------------------------------------------------------
  1169. BOOL OGT_BuildObjects(
  1170.       APTR                         vinfo       ,
  1171.       struct OGT_ObjectSettings   *objectsarray,
  1172.       struct OGT_ObjectLink       *linksarray  ,
  1173.       Object                    ***storage     
  1174.                      );
  1175.  
  1176. struct OGT_ObjectSettings
  1177. {
  1178.    STRPTR          Class;
  1179.    struct TagItem *Settings;
  1180.    struct TagItem *PostSettings;
  1181.    ULONG           Parent;
  1182.    ULONG           Align;
  1183. };
  1184.  
  1185. struct OGT_ObjectLink
  1186. {
  1187.    ULONG           From;
  1188.    ULONG           To;
  1189.    struct TagItem *Map;
  1190.    Tag            *Filter;
  1191. };
  1192. --------------------------------------------------------------------------------
  1193.  
  1194. vinfo è il valore ritornato da OGT_GetVisualInfoA.
  1195.  
  1196. objectsarray definisce i rapporti geometrici fra gli oggetti, e termina con
  1197. Class = NULL.  Settings è un array di tag per NewObject, ma senza OGT_VisualInfo
  1198. (Anche OGT_Parent) e OGT_AlignToObject non sono più necessari, anzi, proprio non
  1199. sarebbero possibili}, che viene inserito dalla funzione.  PostSettings è invece
  1200. un array di tag da mandare all'oggetto, per mezzo del metodo OM_SET, quando
  1201. tutti gli oggetti e la rete di comunicazione sono attivi.  Parent è il numero
  1202. dell'oggetto che è padre di questo oggetto, come Align indica l'oggetto da usare
  1203. per l'allineamento (da specificare solo nel caso in cui l'oggetto da usare per
  1204. l'allineamento non sia l'oggetto che precede quello corrente).  Usando come
  1205. numero OGT_NOOBJECT si indica di non usare il campo.
  1206.  
  1207. linksarray invece definisce la rete di comunicazione tra gli oggetti.  From e To
  1208. sono i numeri degli oggetti da porre in comunicazione, Filter indica quali tag,
  1209. nel dominio di From, devono andare a To e infine Map è la classica applicazione
  1210. dal dominio di From a quello di To.  L'array finisce con From = OGT_NOOBJECT.
  1211. Le liste di tag sono copiate, non referenziate.  Si ricorda infine che tutti gli
  1212. oggetti comunicano di default con l'applicazione, cosa non sempre desiderabile,
  1213. a cui si può ovviare con il seguente tagitem nella taglist Settings:
  1214.  
  1215. --------------------------------------------------------------------------------
  1216.   ...
  1217.   { ICA_TARGET, NULL },
  1218.   ...
  1219. --------------------------------------------------------------------------------
  1220.  
  1221. storage è un puntatore ad un puntatore ad oggetti.  In pratica la funzione
  1222. alloca un array di puntatori ad oggetti e lo riempe con i puntatori agli oggetti
  1223. allocati.  Sarà cura dell'applicazione liberare tale array con FreeVec.
  1224.  
  1225. Per capire meglio la OGT_BuildObjects, è conveniente pensare al nostro problema
  1226. come ad un grafo, in cui objectsarray definisce i nodi e linksarray definisce
  1227. gli archi.
  1228.  
  1229. Nel caso non si voglia usare OGT_BuildObjects per creare gli oggetti, per aprire
  1230. la finestra o per aggiornarla, nel caso che si siano aggiunti degli oggetti a
  1231. finestra già aperta, è necessario chiamare la funzione OGT_RefreshWindow.  Se
  1232. invece si cancellano degli oggetti non c'è bisogno di alcun refresh, sono gli
  1233. oggetti stessi che si cancellano.  Una volta attiva la finestra bisogna gestire
  1234. i messaggi che arrivano da essa, per mezzo delle due funzioni OGT_GetMsg e
  1235. OGT_ReplyMsg.  Gli unici messaggi IDCMP di interesse sono di tipo *CLOSEWINDOW e
  1236. *IDCMPUPDATE.  Non è necessario specificare anche altri IDCMP nella definizione
  1237. della finestra, per permettere alla libreria di funzionare.  A questo ci pensa
  1238. essa stessa, aggiungendo i flag mancanti, ma comunicando all'applicazione solo
  1239. quelli specificati.
  1240.  
  1241. La funzione OGT_GetWindowPtr, come pare ovvio dal nome, ritorna il puntatore
  1242. alla finestra relativa all'applicazione.  E' infatti cura della libreria
  1243. l'apertura, la gestione e la chiusura della finestra.
  1244.  
  1245. Infine la funzione OGT_FreeVisualInfo chiude tutto, oggetti e finestra,
  1246. liberando le risorse.
  1247.  
  1248.  
  1249.  
  1250. *Implementazione*
  1251.  
  1252. Nel discutere degli oggetti, dei loro tag e delle funzioni che li controllano si
  1253. sono già fatte delle digressioni su come le varie cose sono state implementate.
  1254. Naturalmente non è possibile descrivere qui tutte le tecniche adottate, si
  1255. farebbe molto prima a riportare il codice.  Si sono scelte così quelle ritenute
  1256. più interessanti.
  1257.  
  1258.  
  1259. **La struttura GadgetInfo**
  1260.  
  1261. Tale struttura è di basilare importanza per tutti i BOOPSI di tipo gadget, in
  1262. quanto viene usata in quasi tutti i metodi relativi ad essi.  E' a sola lettura
  1263. e viene creata da Intuition.  Il problema è proprio questo, viene creata solo da
  1264. Intuition e non esiste alcuna chiamata pubblica per crearla.  La OGT possiede
  1265. tutta una serie di nuove funzioni per il controllo trasparente degli short-cut,
  1266. dell'HELP, per la cancellazione degli oggetti, funzioni che, nello spirito di
  1267. una programmazione orientata agli oggetti, sono state inglobate nelle classi
  1268. stesse e a cui si accede per mezzo di nuovi metodi, alcuni dei quali pubblici.
  1269.  
  1270. Il problema davanti al quale ci si è trovati consiste proprio nell'allocare in
  1271. maniera legale una struttura GadgetInfo, e l'unico modo è per mezzo della
  1272. funzione SetGadgetAttrs.  Tale funzione manda un metodo OM_SET ad un oggetto, ma
  1273. a noi interessa mandare un generico metodo ad un oggetto.  La soluzione che si è
  1274. adottata consiste nel creare una classe privata, a cui mandare un metodo OM_SET,
  1275. con le indicazioni sul metodo reale che si vuole eseguire e il suo target.  In
  1276. questo modo si sono potute sviluppare le classi senza il bisogno di strani
  1277. kludge.
  1278.  
  1279.  
  1280.  
  1281. **Accesso condiviso agli oggetti**
  1282.  
  1283. Gli oggetti della OGT possono essere usati da più task contemporaneamente, senza
  1284. problemi di coerenza, i BOOPSI no.  La questione potrebbe non apparire
  1285. importante, dato che ben difficilmente qualcuno disegnerà un'applicazione che
  1286. faccia uso di più task per controllare una stessa finestra, ma si dimentica che
  1287. tutte le finestre sono sempre sotto il controllo di due task, quello
  1288. dell'applicazione e l'input.device.  E come in tutte le situazioni con risorse
  1289. condivise è necessario un qualche meccanismo di protezione contro accessi
  1290. contemporanei.  Sotto 2.0 tale meccanismo non c'è e questo rende i normali
  1291. BOOPSI non totalmente affidabili.  Se altri si sono cimentati nell'uso dei
  1292. BOOPSI e non hanno riscontrato questi problemi, è solo per ragioni
  1293. probabilistiche:  finchè si usano solo degli oggetti di tipo BUTTONGCLASS o
  1294. STRGCLASS, molto semplici e quindi veloci, la probabilità che l'utente modifichi
  1295. lo stato di un oggetto (cioè applichi un qualche metodo all'oggetto tramite la
  1296. input.device) nello stesso istante in cui l'applicazione aggiorni lo stato dello
  1297. stesso oggetto è quasi zero.  Noi ad esempio ce ne siamo accorti solo creando
  1298. uno oggetto di tipo SHOWLIST_OGT_CLASS per mostrare un testo, con attaccati
  1299. altri due oggetti di tipo SCROLLER_OGT_CLASS per permettere all'utente lo scroll
  1300. e facendo in modo che l'applicazione muovesse continuamente il testo in
  1301. orizzontale, con l'utente che cercava di interferire con il movimento agendo
  1302. sugli scroller.  Con un tale sistema era molto facile provocare un blocco della
  1303. macchina.
  1304.  
  1305. La soluzione trovata consiste in un semaforo per ogni finestra, in modo che solo
  1306. un task alla volta possa accedere agli oggetti attaccati ad essa.
  1307.  
  1308. Purtroppo anche in Commodore se ne sono accorti e nella nuova revisione del
  1309. sistema operativo, la 3.0, hanno adottato un meccanismo di protezione.
  1310. Purtroppo, perchè la soluzione è peggiore del male:  il problema era impedire
  1311. all'input.device e all'applicazione di accedere contemporaneamente agli oggetti
  1312. e la soluzione trovata consiste nel bloccare l'input.device tutte le volte che
  1313. un altro task accede ad un oggetto.  Bloccare l'input.device significa bloccare
  1314. anche i movimenti del mouse ed impedire l'input da tastiera.  Non è affatto
  1315. gradevole esteticamente, ancor meno dal punto di vista funzionale, dato che
  1316. hanno impedito l'accesso contemporaneo ma hanno permesso situazioni di deadlock:
  1317. se un oggetto, per qualche motivo, apre un classico requester 'Ok/Cancel',
  1318. l'utente non potrà mai rispondere e la macchina rimarrà bloccata.  Per noi
  1319. questo è inaccettabile e pregheremmo tutti di far presente la situazione alla
  1320. Commodore.
  1321.  
  1322.  
  1323.  
  1324. **Uso del DOS**
  1325.  
  1326. Ci sono classi, come la SHOWLIST_OGT_CLASS, che devono usare il DOS per alcune
  1327. loro funzioni.  Tutto è tranquillo se le istanze di quelle classi girano nel
  1328. contesto di un processo, al quale è permesso l'uso del DOS, mentre ci sarà un
  1329. sicuro crash se le stesse girano nel contesto dell'input.device, un task.  Per
  1330. ovviare a questo inconveniente, le classi controllano in che contesto stanno
  1331. operando e nel caso si tratti di un task lanciano un processo parallelo,
  1332. sincrono o asincrono, e lasciando che sia esso a gestire il compito prescritto.
  1333. C'è anche il caso della classe ASLREQ_OGT_CLASS, che crea un processo asincrono
  1334. in ogni caso.  Questo permette lo svolgersi di altri compiti nel frattempo, uno
  1335. dei quali potrebbe essere il ridimensionamento della finestra stessa (cosa non
  1336. possibile se l'oggetto restasse in attesa, per il problema della condivisione
  1337. delle risorse).  Se poi l'utente decide di cancellare il requester, non
  1338. succederà assolutamente niente:  il processo si chiuderà senza generare alcun
  1339. messaggio.
  1340.  
  1341.  
  1342.  
  1343. **Lo stack**
  1344.  
  1345. Questo è un problema molto importante in quanto i BOOPSI, per loro natura,
  1346. consumano molto stack.  Mandare un metodo ad un oggetto si trasforma in realtà
  1347. in una chiamata di funzione e se si pensa che gli oggetti possono reagire ad un
  1348. metodo mandando a vari oggetti altri metodi, che gli oggetti possono essere
  1349. raccolti in catene di lunghezza arbitraria, si capisce che il numero di funzioni
  1350. chiamate può essere molto alto:  da prove fatte con il programma ViewFile
  1351. (commentato nel seguito), che riunisce 4 oggetti complessi insieme, si è trovato
  1352. che si possono avere anche 50 chiamate nidificate.  Imporre una dimensione
  1353. minima per lo stack dell'applicazione in base alla configurazione
  1354. dell'interfaccia non ha senso, perchè la stessa interfaccia deve anche girare
  1355. sotto input.device, con uno stack di 4K.  Per fortuna il 2.0 ci è venuto
  1356. incontro, per mezzo della funzione SwapStack.  Dato che i BOOPSI funzionano
  1357. mandando tutti i metodi ad un'unica funzione (Dispatcher) per ogni classe, che
  1358. poi si occupa di smistare i vari metodi alle funzioni di competenza, si è posto
  1359. all'entrata di quella funzione un controllo su quanto stack sia ancora
  1360. disponibile.  Se scende sotto i 2K, si alloca un nuovo stack di 10K e con
  1361. SwapStack lo si installa.  Al ritorno dalla funzione si ripristina la situazione
  1362. precedente e si libera ciò che si era eventualmente preso.  Uno stack dinamico,
  1363. che risolve tutti i problemi, in qualunque contesto.
  1364.  
  1365.  
  1366.  
  1367. *Esempio di utilizzo della libreria*
  1368.  
  1369. Fino ad ora si è parlato in modo teorico dei singoli aspetti della OGT e ci
  1370. sembra giunto il momento di raggruppare il tutto in un esempio pratico.
  1371.  
  1372. Nell'esempio vogliamo far vedere:
  1373.  
  1374.  + come si definiscono le caratteristiche geometriche degli oggetti.
  1375.  + come si definisce la rete delle comunicazioni fra gli oggetti.
  1376.  + cosa si deve fare per avere l'adattamento ai font.
  1377.  + un oggetto che mostri testo.
  1378.  + un oggetto che selezioni un file.
  1379.  + un oggetto che risponda al rilascio delle icone.
  1380.  
  1381. Si può vedere il risultato nella Fig.1.  Dalla figura si vede che servono anche
  1382. due SCROLLER, inseriti nel bordo e iniziamo a definire proprio quelli:
  1383.  
  1384. --------------------------------------------------------------------------------
  1385.   struct TagItem Object1[] =
  1386.   {
  1387.      { GA_Immediate       , TRUE                },
  1388.      { GA_FollowMouse     , TRUE                },
  1389.      { GA_RelVerify       , TRUE                },
  1390.      { ICA_TARGET         , NULL                },
  1391.      { OGT_SetDimReference, OGT_X_Dim_Relative|
  1392.                             OGT_Y_Dim_Relative  },
  1393.      { GA_RightBorder     , TRUE                },
  1394.      { PGA_Freedom        , FREEVERT            },
  1395.      { TAG_DONE                                 },
  1396.   };
  1397.  
  1398.   struct TagItem Object2[] =
  1399.   {
  1400.      { GA_Immediate       , TRUE                },
  1401.      { GA_FollowMouse     , TRUE                },
  1402.      { GA_RelVerify       , TRUE                },
  1403.      { ICA_TARGET         , NULL                },
  1404.      { OGT_SetDimReference, OGT_X_Dim_Relative|
  1405.                             OGT_Y_Dim_Relative  },
  1406.      { GA_BottomBorder    , TRUE                },
  1407.      { PGA_Freedom        , FREEHORIZ           },
  1408.      { TAG_DONE                                 },
  1409.   };
  1410. --------------------------------------------------------------------------------
  1411.  
  1412. Così si sono definite le loro caratteristiche geometriche:  devono essere nel
  1413. bordo (*Border) e devono essere grandi come tutto il dominio in cui risiedono
  1414. (OGT_SetDimReference).  Questi oggetti servono per spostare il testo e allora
  1415. definiamo subito l'oggetto che mostra questo testo:
  1416.  
  1417. --------------------------------------------------------------------------------
  1418.   struct TagItem Object3[] =
  1419.   {
  1420.      { GA_Immediate       , TRUE                },
  1421.      { GA_FollowMouse     , TRUE                },
  1422.      { GA_RelVerify       , TRUE                },
  1423.      { ICA_TARGET         , NULL                },
  1424.      { OGT_SetDimReference, OGT_X_Dim_Relative|
  1425.                             OGT_Y_Dim_Relative  },
  1426.      { GA_Height          , -14                 },
  1427.      { OGTSL_UseNumPad    , TRUE                },
  1428.      { TAG_DONE                                 },
  1429.   };
  1430. --------------------------------------------------------------------------------
  1431.  
  1432. Quest'oggetto è all'interno della finestra (nessun *Border) e dato che vogliamo
  1433. anche un po' di spazio per un oggetto che seleziona il nome del file da
  1434. visualizzare, lo facciamo grande come il dominio meno l'altezza dell'altro
  1435. oggetto.  OGTSL_UseNumPad indica che vogliamo usare il tastierino numerico per
  1436. lo scroll.  Manca un solo oggetto che definiamo con:
  1437.  
  1438. --------------------------------------------------------------------------------
  1439.   struct TagItem Object4[] =
  1440.   {
  1441.      { OGT_SetDimReference, OGT_X_Dim_Relative },
  1442.      { OGT_SetPosHandle   , OGT_Y_Bottom       },
  1443.      { GA_RelBottom       , 0                  },
  1444.      { GA_Height          , 14                 },
  1445.      { GA_Text            , "_F"               },
  1446.      { OGT_TextPlacement  , OGT_Text_HIDE      },
  1447.      { OGTAR_Type         , ASL_FileRequest    },
  1448.      { OGTAR_ShowSelected , TRUE               },
  1449.      { TAG_DONE                                }
  1450.   };
  1451. --------------------------------------------------------------------------------
  1452.  
  1453. L'oggetto deve essere posizionato nella parte bassa della finestra e questo ci
  1454. permette di mostrare un nuovo modo di gestire la posizione degli oggetti:  per
  1455. mezzo del tag OGT_SetPosHandle si cambia il punto dell'oggetto che viene usato
  1456. per posizionarlo.  Normalmente è l'angolo in alto a sinistra ma a noi conviene
  1457. definire la sua posizione per mezzo di quello in basso a sinistra
  1458. (OGT_Y_Bottom).  Poi abbiamo specificato GA_RelBottom per porre quell'angolo
  1459. come relativo al bordo inferiore del dominio.  Tale combinazione ci consente di
  1460. cambiare l'altezza dell'oggetto senza doverci preoccupare anche di ridefinire la
  1461. sua posizione, come invece sarebbe necessario con i gadget normali.
  1462.  
  1463. Di nuovo c'è pure il controllo dell'oggetto per mezzo di short-cut (GA_Text),
  1464. che però è invisibile (OGT_TextPlacement).  Seguono due tag specifici per gli
  1465. oggetti di questa classe, OGTAR_Type e OGTAR_ShowSelected, che creano un file
  1466. requester con visualizzato il file selezionato.  Gli oggetti di questa classe
  1467. sono di default sensibili al rilascio delle icone, quindi anche un'altra delle
  1468. nostre specifiche è soddisfatta.
  1469.  
  1470. Abbiamo definito le caratteristiche geometriche degli oggetti, ora rimango due
  1471. punti, l'adattamento al font e la rete di comunicazioni, e riprendiamo proprio
  1472. dalla rete, che viene schematizzata in Fig.2.
  1473.  
  1474. Gli oggetti 1 e 2 emettono PGA_Top, mentre 3 capisce OGTSL_VertPort e
  1475. OGTSL_HoriPos, quindi:
  1476.  
  1477. --------------------------------------------------------------------------------
  1478.   struct TagItem Map1to3[] =
  1479.   {
  1480.      { PGA_Top , OGTSL_VertPos },
  1481.      { TAG_DONE                },
  1482.   };
  1483.  
  1484.   struct TagItem Map2to3[] =
  1485.   {
  1486.      { PGA_Top , OGTSL_HoriPos },
  1487.      { TAG_DONE                },
  1488.   };
  1489. --------------------------------------------------------------------------------
  1490.  
  1491. Il reciproco, dal 3 a 1-2, è un poco più complesso, in quanto non solo si deve
  1492. riferire la posizione, ma anche le dimensioni totali e visibili:
  1493.  
  1494. --------------------------------------------------------------------------------
  1495.   struct TagItem Map3to1[] =
  1496.   {
  1497.      { OGTSL_VertPos    , PGA_Top     },
  1498.      { OGTSL_VertTotal  , PGA_Total   },
  1499.      { OGTSL_VertVisible, PGA_Visible },
  1500.      { TAG_DONE                       },
  1501.   };
  1502.  
  1503.   Tag Filter3to1[] =
  1504.   {
  1505.      OGTSL_VertPos    ,
  1506.      OGTSL_VertTotal  ,
  1507.      OGTSL_VertVisible,
  1508.      TAG_DONE
  1509.   };
  1510.  
  1511.  
  1512.   struct TagItem Map3to2[] =
  1513.   {
  1514.      { OGTSL_HoriPos    , PGA_Top     },
  1515.      { OGTSL_HoriTotal  , PGA_Total   },
  1516.      { OGTSL_HoriVisible, PGA_Visible },
  1517.      { TAG_DONE                       },
  1518.   };
  1519.  
  1520.   Tag Filter3to2[] =
  1521.   {
  1522.      OGTSL_HoriPos    ,
  1523.      OGTSL_HoriTotal  ,
  1524.      OGTSL_HoriVisible,
  1525.      TAG_DONE
  1526.   };
  1527. --------------------------------------------------------------------------------
  1528.  
  1529. Qui si sono anche specificati dei filtri, cosa utile per diminuire il numero di
  1530. messaggi da mandare fra i vari oggetti, in quanto l'oggetto 3 emette molti
  1531. messaggi, che possono non interessare gli altri oggetti e per mezzo dei filtri
  1532. solo i messaggi significativi per un oggetto verranno mandati ad esso.
  1533.  
  1534.  
  1535. Ora gli oggetti 1,2 e 3 sono legati, qualunque cosa si faccia ad uno si riflette
  1536. sugli altri.  Infine attacchiamo anche 4 a 3:
  1537.  
  1538. --------------------------------------------------------------------------------
  1539.   struct TagItem Map4to3[] =
  1540.   {
  1541.      { OGTAR_FullFileName, OGTSL_FileToLoadByName },
  1542.      { TAG_DONE                                   },
  1543.   };
  1544.  
  1545.   Tag Filter4to3[] =
  1546.   {
  1547.      OGTAR_FullFileName,
  1548.      TAG_DONE
  1549.   };
  1550. --------------------------------------------------------------------------------
  1551.  
  1552. e con questo la definizione dell'interfaccia è completa, ma per costruire
  1553. realmente l'interfaccia bisogna unire insieme tutte queste strutture:
  1554.  
  1555. --------------------------------------------------------------------------------
  1556.    struct OGT_ObjectSettings ListOfObjects[] =
  1557.    {
  1558.       { SCROLLER_OGT_CLASS, Object1,
  1559.                             NULL   ,
  1560.                             OGT_NOOBJECT,
  1561.                             OGT_NOOBJECT },
  1562.       { SCROLLER_OGT_CLASS, Object2,
  1563.                             NULL   ,
  1564.                             OGT_NOOBJECT,
  1565.                             OGT_NOOBJECT },
  1566.       { SHOWLIST_OGT_CLASS, Object3,
  1567.                             NULL   ,
  1568.                             OGT_NOOBJECT,
  1569.                             OGT_NOOBJECT },
  1570.       {   ASLREQ_OGT_CLASS, Object4,
  1571.                             NULL   ,
  1572.                             OGT_NOOBJECT,
  1573.                             OGT_NOOBJECT },
  1574.       { NULL                             },
  1575.    };
  1576.  
  1577.    struct OGT_ObjectLink ListOfLinks[] =
  1578.    {
  1579.       { 0, 2, Map1to3             },
  1580.       { 1, 2, Map2to3             },
  1581.       { 2, 0, Map3to1, Filter3to1 },
  1582.       { 2, 1, Map3to2, Filter3to2 },
  1583.       { 3, 2, Map4to3, Filter4to3 },
  1584.       { OGT_NOOBJECT              },
  1585.    };
  1586. --------------------------------------------------------------------------------
  1587.  
  1588. L'adattamento ai font è una cosa che si può definire indipendentemente dalla
  1589. definizione dell'interfaccia:  al momento della chiamata a OGT_GetVisualInfo,
  1590. oltre i tag per definire la finestra si passano i seguenti tag:
  1591.  
  1592. --------------------------------------------------------------------------------
  1593.   { OGT_TextFont         , myfont           },
  1594.   { OVI_GimmeZeroZero    , TRUE             },
  1595.   { OVI_AdaptWidthToFont , TRUE             },
  1596.   { OVI_AdaptHeightToFont, TRUE             },
  1597.   { OGT_ScaleLeft        , OGT_FontRelative },
  1598.   { OGT_ScaleTop         , OGT_FontRelative },
  1599.   { OGT_ScaleWidth       , OGT_FontRelative },
  1600.   { OGT_ScaleHeight      , OGT_FontRelative },
  1601.   { OGT_DomainXscale     , ~0               },
  1602.   { OGT_DomainYscale     , ~0               },
  1603. --------------------------------------------------------------------------------
  1604.  
  1605. con cui si definiscono tutti gli oggetti come dimensionati relativamente al font
  1606. usato e si chiede di ridimensionare la finestra, sempre in proporzione al font
  1607. usato.
  1608.  
  1609. Così come la si è definita l'interfaccia funziona, infatti specificando un file
  1610. per mezzo della tastiera, del file-requester o di un'icona si provoca la sua
  1611. lettura e la sua visualizzazione, e il tutto non richiede il minimo intervento
  1612. da parte dell'applicazione, che deve solo attendere il messaggio CLOSEWINDOW!
  1613.  
  1614. Ora però il rilascio di un'icona è riconosciuto solo dall'oggetto 4, molto
  1615. piccolo rispetto al resto della finesta, e quindi sarebbe interessante fare in
  1616. modo che anche rilasciando un'icona sull'oggetto 3 il file venga caricato.
  1617. Vediamo come.
  1618.  
  1619. La prima cosa è comandare l'oggetto 3 di riconoscere il rilascio, per mezzo di
  1620. OGT_AppGadget = TRUE.  Poi bisogna mettere in comunicazione 3 con 4:
  1621.  
  1622. --------------------------------------------------------------------------------
  1623.   struct TagItem Map3to4[] =
  1624.   {
  1625.      { OGT_DroppedIcon, OGTAR_FullFileName },
  1626.      { TAG_DONE                            }
  1627.   };
  1628.  
  1629.   Tag Filter3to4[] =
  1630.   {
  1631.      OGT_DroppedIcon,
  1632.      TAG_DONE
  1633.   };
  1634. --------------------------------------------------------------------------------
  1635.  
  1636. ma se lo proviamo ci accorgiamo che funziona a metà:  l'icona viene ricevuta da
  1637. 3, che la manda a 4 (ne siamo sicuri perchè viene aggiornato lo string gadget),
  1638. ma poi non viene caricato il file.  Il motivo dell'insuccesso è semplice:  ci
  1639. siamo imbattuti in un meccanismo di protezione automatica dei BOOPSI.  Se si
  1640. guarda bene la Fig.2, fra 1 e 3, fra 2 e 3, fra 3 e 4, la rete di comunicazione
  1641. forma dei cicli.  Per capire bene cosa significa, poniamoci nel caso in cui
  1642. l'utente dia un "Page Down" da tastiera.  Allora 3 scrolla verso il basso e
  1643. comunica ad 1 la nuova posizione, il quale, per tutta risposta, rimanda a 3 il
  1644. messaggio di modifica della posizione.  Ora 3 riceve il messaggio, lo processa e
  1645. lo rimanda a 1, così all'infinito.  Per fortuna i BOOPSI hanno un dispositivo
  1646. automatico di riconoscimento dei cicli e se arriva un messaggio che chiude un
  1647. ciclo, semplicemente lo rifiutano.  E' proprio quello che è successo a noi:  3
  1648. manda a 4 un messaggio, 4 lo processa e ne manda un altro a 3, il quale
  1649. individua un ciclo e lo scarta.
  1650.  
  1651. Se vogliamo che l'interfaccia funzioni a dovere, bisogna far intervenire
  1652. l'applicazione, rompendo il ciclo fra 3 e 4.  Invece di far comunicare 3 con 4,
  1653. lo si fa comunicare con l'applicazione, togliendo il tag ICA_TARGET dalla sua
  1654. definizione.  Quando arriva un messaggio, l'applicazione lo identifica come da 3
  1655. e lo rimanda a 4, che poi lo rimbalza a 3, che questa volta lo processa
  1656. correttamente.
  1657.